<template>
  <el-row>
    <div>
      <span>供货价格方式：</span>
      <el-radio-group
        v-model="purchaseType"
        @change="handleSwitchPurchaseStatus"
      >
        <el-radio label="1">统一进价</el-radio>
        <el-radio label="2">区域进价</el-radio>
      </el-radio-group>
    </div>
    <div class="refer-cities-wrap">
      <span>设置参照城市关系：</span>
      <el-button size="large" type="text" @click="handleSetReferCities">设置</el-button>
    </div>
    <el-row>
      <skus-table
        ref="skusTable"
        :tableHeight="480"
        :dataSource="TableInfo.list"
        :columns="TableInfo.columns"
        :loading="TableInfo.loading"
        @handleRowSpecialChange="handleRowSpecialChange"
      >
        <!-- 按钮操作栏 -->
        <BtnRender slot="content_context" :render="renderBtnsBar" />
      </skus-table>
    </el-row>
    <ShowReferCitiesDialog
      :visible.sync="referCities.visible"
      :areaCodes="saleAreaNos.join(',')"
      :supplierCode="supplierInfo.supplyUuid"
      :dataSource.sync="referCities.list"
      :purchase-type="purchaseType"
      @getReferCities="updateInfoBySetReferCities"
    />
    <ShowListDialog
      dialog-title="售价预览"
      :visible.sync="previewSalePrice.visible"
      :table-columns="previewSalePrice.columns"
      :table-data="previewSalePrice.list"
    />
  </el-row>
</template>
<script>
import { mapGetters } from 'vuex';
import SkusTable from '@/components/skusTable';
import BtnRender from '@/components/JSXRender/BtnRender';
import ShowReferCitiesDialog from '../../components/ReferCitiesUpdate/ShowReferCitiesDialog';
import ShowListDialog from '@/components/ShowListDialog';
import { getListPageBtnsBar } from '@/utils/getBtnsRender';
import { TableInfo } from '@/utils/getUtils';
import { createExcelByExport, generateUuid, isResponseSuccess } from '@/utils/bizUtils';
import {
  handlePriceChangeForSingleAdd,
  hasEmptyPriceForSingle,
  getPriceChangeForSingleAdd,
  handlePriceChangeForMultipleAdd,
  hasEmptyPriceForMultiple,
  getPriceChangeForMultipleAdd,
} from '@/utils/price';
import {
  SINGLE_TABLE_COLUMNS,
  MULTIPLE_TABLE_COLUMNS,
  VIEW_SINGLE_TABLE_COLUMNS,
  VIEW_MULTIPLE_TABLE_COLUMNS,
} from './constants';
import { SALE_PRICE_TABLE_COLUMNS } from '../../saleAreaAdd/PurchaseInfo/constants/previewSalePrice';
import {
  EVENT_BUS,
  PURCHASE_UNIT,
  ERROR_MSG_COL,
  PURCHASE_TYPE,
  PURCHASE_TYPE_LABEL
} from '../constants';
import {
  importTemplateForCreateUrl,
  importTemplateForCreateSteelUrl,
  downLoadTemplateForCreateService,
  exportErrorPriceDataService,
  prepareViewSalePriceService
} from '@/api/commodity/commodityInfoEdit/saleAreaAdd';
import {
  getSupplySkuCityPurchasePriceForAlignmentSaleAreaService,
  commitProductSupplySaleAreaSkuRecordForAlignmentSaleAreaService
} from '@/api/commodity/commodityInfoEdit/saleAreaAlign';
export default {
  components: {
    SkusTable,
    BtnRender,
    ShowReferCitiesDialog,
    ShowListDialog
  },
  data () {
    return {
      purchaseType: PURCHASE_TYPE.Area,
      TableInfo: new TableInfo({ columns: SINGLE_TABLE_COLUMNS, dimensionKey: 'skuNo' }),
      referCities: {
        visible: false,
        list: [],
        finalResults: []
      },
      btnLoading: {
        exportAbnormal: false, // 导出异常数据loading
        export: false, // 模板导出loading
        submit: false, // 提交loading
      },
      isMultiple: false, // 是否为进价多计量
      isPurchaseMultiUnit: '', // 是否为进价多计量类型值
      skuNos: [], // 当前进价skuNo集合
      supplierInfo: {}, // 供应商信息
      taxRateInvoiceInfo: {}, // 税类发票信息
      saleAreaNos: [], // 销售区域编码集合
      previewSalePrice: {
        visible: false,
        loading: false,
        columns: SALE_PRICE_TABLE_COLUMNS,
        list: []
      }
    }
  },
  created () {
    this.loadEventBusListeners()
  },
  computed: {
    ...mapGetters('permissions/systemBtns', ['showBtn']),
    // 没有异常数据
    hasNoErrMsgs () {
      const hasNoErrMsgs = this.TableInfo.list.every(item => !item?.errorMsg)
      return hasNoErrMsgs
    },
    // 不能预览售价
    cannotPreviewSalePrice () {
      const hasNoRefer = this.referCities.list.length == 0
      const cannotPreview = this.TableInfo.isNullList() && hasNoRefer
      return cannotPreview
    }
  },
  methods: {
    // 渲染按钮操作栏
    renderBtnsBar (h) {
      const btnBars = [
        {
          label: '预览售价',
          method: this.handlePreviewSalePrice,
          disabled: this.cannotPreviewSalePrice,
          loading: this.previewSalePrice.loading
        },
        {
          label: '导出异常数据',
          method: this.handleExportAbnormalData,
          loading: this.btnLoading.exportAbnormal,
          disabled: this.hasNoErrMsgs
        },
        {
          label: '一键清除异常数据',
          method: this.handleClearAbnormalData,
          disabled: this.hasNoErrMsgs
        },
        {
          label: '模板导出',
          method: this.handleTempExport,
          loading: this.btnLoading.export,
          disabled: this.TableInfo.isNullList()
        },
        {
          label: '模板导入',
          action: this.isMultiple ? importTemplateForCreateSteelUrl : importTemplateForCreateUrl,
          methods: { handleUploadSuccess: this.handleUploadSuccess },
          isImport: true,
          loadingFn: this.TableInfo.setLoading,
          data: {
            supplyUuid: this.supplierInfo.supplyUuid, // 供应商编码
            purchasePriceType: this.purchaseType, // 供货价格方式 - 2为区域进价
            manySupply: '1' // 是否多供，1为多供
          }
        },
        {
          label: '提交',
          method: this.handleSubmit,
          loading: this.btnLoading.submit,
          disabled: this.TableInfo.isNullList(),
          hasAuth: true
        }
      ]
      return getListPageBtnsBar(h, btnBars, this.showBtn)
    },
    // 加载event-bus的监听事件
    loadEventBusListeners () {
      // 供应商变更
      EVENT_BUS.$on('change-supplier', ({ supplierInfo, taxRateInvoiceInfo }) => {
        this.referCities.list = [] // 清空参照
        this.TableInfo.clearList() // 清空进价表格
        this.supplierInfo = supplierInfo ?? {} // 供应商信息
        this.taxRateInvoiceInfo = taxRateInvoiceInfo ?? {} // 税类发票信息
        this.saleAreaNos = supplierInfo?.saleAreaNos ?? [] // 销售区域编码集合
      })
      // 销售区域变更
      EVENT_BUS.$on('change-areas', saleAreaNos => {
        this.referCities.list = [] // 清空参照
        this.TableInfo.clearList() // 清空进价表格
        this.saleAreaNos = saleAreaNos ?? [] // 销售区域编码集合
      })
      // 商品信息删除sku时，删除对应进价SKU
      EVENT_BUS.$on('delete-sku', row => {
        this.TableInfo.setList(this.TableInfo.list.filter(item => item.skuNo != row.skuNo))
      })
      // 商品信息提交或批量删除（删除所有单计量或删除所有多计量）时，更新sku编码。
      EVENT_BUS.$on('update-skus', skuNos => {
        this.skuNos = skuNos
        if (this.TableInfo.isNullList()) return
        // 过滤已删除对应进价SKU
        const filterList = this.TableInfo.list.filter(
          item => skuNos.includes(item.skuNo)
        )
        this.TableInfo.setList(filterList)
      })
      // 商品信息提交后进价信息加载
      EVENT_BUS.$on('commit-product-success', () => {
        this.referCities.list = [] // 清空参照
        this.TableInfo.clearList() // 清空进价表格
        if (EVENT_BUS?._data?.skuList) { // 商品信息提交后更新当前进价是否为多计量状态
          this.isPurchaseMultiUnit = EVENT_BUS?._data?.skuList[0]?.isPurchaseMultiUnit
          this.isMultiple = this.isPurchaseMultiUnit == PURCHASE_UNIT.Multiple
          this.updatePurchaseColumns()
        }
      })
    },
    // 切换供货价格方式
    handleSwitchPurchaseStatus (val) {
      if (this.referCities.list.length == 0) return
      this.confirmBySwitchPurchaseType(val)
    },
    // 预览售价
    async handlePreviewSalePrice () {
      const isMaintainCostPrice = this.TableInfo.list.some(item => !item.mainUnitCostPrice)
      if (isMaintainCostPrice) return this.$message.warning('请维护所有成本价后再进行售价预览')
      this.setPreviewSalePriceInfo()
    },
    // 导出异常数据
    async handleExportAbnormalData () {
      const errorData = this.TableInfo.list.filter(item => item.errorMsg)
      const data = {
        isPurchaseMultiUnit: this.isPurchaseMultiUnit,
        errorData
      }
      const loadingFn = state => { this.btnLoading.exportAbnormal = state }
      const res = await exportErrorPriceDataService(data, loadingFn)
      createExcelByExport({ excelTitle: `销售区域进价信息异常数据_${generateUuid()}`, res })
    },
    // 一键清除异常数据
    handleClearAbnormalData () {
      this.TableInfo.setList(this.TableInfo.list.filter(item => !item.errorMsg))
    },
    // 模板导出
    async handleTempExport () {
      const uuid = generateUuid()
      const data = this.getExportParams(uuid)
      const loadingFn = state => { this.btnLoading.export = state }
      const res = await downLoadTemplateForCreateService(data, loadingFn)
      createExcelByExport({ excelTitle: `批量修改销售区域-进价信息_${uuid}`, res })
    },
    // 模板导入成功
    handleUploadSuccess (res) {
      if (!isResponseSuccess(res)) return
      let importList = (res?.retData ?? []).map(item => {
        const row = { ...item, ...this.taxRateInvoiceInfo }
        this.handleRowSpecialChange({ row })
        return row
      })
      if (this.purchaseType == PURCHASE_TYPE.Unify) {
        const defaultCityInfo = _.pick(
          this.referCities.finalResults[0],
          ['saleAreaUuid', 'saleAreaName', 'templateCityUuid', 'templateCityName']
        )
        importList = importList.map(item => ({
          ...item,
          ...defaultCityInfo
        }))
      }
      this.TableInfo.setList(importList)
    },
    // 提交
    handleSubmit () {
      const { hasEmptyVal, msg } = this.isMultiple
        ? hasEmptyPriceForMultiple(this.TableInfo.list)
        : hasEmptyPriceForSingle(this.TableInfo.list)
      if (hasEmptyVal) return this.$message.warning(msg)
      if (this.validatePriceIsConsistent()) return this.$message.warning('请确保成本价和公式计算结果一致再提交')
      if (!EVENT_BUS._data.launchReason) return this.$message.warning('发起原因不能为空')
      this.submitPurchaseInfo()
    },
    // 设置参照城市关系
    handleSetReferCities () {
      this.referCities.visible = true
    },
    // 表格input发生变化
    handleRowSpecialChange ({ row }) {
      this.isMultiple
        ? handlePriceChangeForMultipleAdd(row)
        : handlePriceChangeForSingleAdd(row)
    },
    // 更新设置参照后的进价信息
    updateInfoBySetReferCities (referCitiesList) {
      this.referCities.finalResults = referCitiesList
      this.updatePurchaseListBySetReferCities()
      this.updatePurchaseColumns()
    },
    // 更新进价表格数据 by 设置参照城市
    async updatePurchaseListBySetReferCities () {
      const updateList = await this.getCartesianProductBySkuMergeReferCities()
      updateList.forEach(row => {
        this.handleRowSpecialChange({ row })
      })
      this.TableInfo.setList(updateList)
    },
    // 更新表列
    updatePurchaseColumns () {
      const MAX_LIMITS = 5000
      const processExceedLimits = () => {
        const content = `设置参照城市后的进价信息数量超过${MAX_LIMITS}条，请导出模板进行调价`
        const options = {
          type: 'warning',
          showClose: false,
          closeOnClickModal: false,
          closeOnPressEscape: false
        }
        this.$alert(content, '提示', options).then(() => {
          this.TableInfo.setColumns(this.isMultiple ? VIEW_MULTIPLE_TABLE_COLUMNS : VIEW_SINGLE_TABLE_COLUMNS)
        })
      }
      const processNotExceedLimits = () => {
        this.TableInfo.setColumns(this.isMultiple ? MULTIPLE_TABLE_COLUMNS : SINGLE_TABLE_COLUMNS)
      }
      this.TableInfo.list.length > MAX_LIMITS ? processExceedLimits() : processNotExceedLimits()
    },
    // 获取初始化价格实例
    getInitPriceVo() {
      const singlePriceVo = {
        freightRatio: 0, // 运费比例或金额
        packRatio: 0, // 包装比例或金额
        processChargesRatio: 0, // 加工费比例或金额
        rebateRatio: 0, // 返利折合比例或金额
        mainUnitCostPrice: 0, // 成本价
        mainPurchasePrice: 0, // 主计量进价
      }
      const multiplePriceVo = {
        ...singlePriceVo,
        actualConvertRatioCostPrice: 0, // 实际转换率辅计量成本价
        theoryConvertRatioCostPrice: 0, // 理论转换率辅计量成本价
      }
      return this.isMultiple ? multiplePriceVo : singlePriceVo
    },
    // 更新进价表格数据 by 获取已有价格
    async getSupplySkuCityPriceMaps (targetList) {
      const data = {
        supplyUuid: this.supplierInfo.supplyUuid,
        getSupplySkuCityPurchasePriceForAlignmentSaleAreaDetailParams: targetList.map(item => ({
          skuNo: item.skuNo,
          saleCityUuid: item.templateCityUuid
        }))
      }
      const res = await getSupplySkuCityPurchasePriceForAlignmentSaleAreaService(data, this.TableInfo.setLoading)
      return res?.retData?.skuSaleCityPurchasePriceVoMap ?? {}
    },
    // 获取商品信息和参照城市信息笛卡尔积后的集合
    async getCartesianProductBySkuMergeReferCities () {
      const skuList = EVENT_BUS._data?.skuList ?? [] // 商品信息sku明细集合
      // 获取参照城市所需字段信息
      const getReferCityInfo = cityInfo => (_.pick(cityInfo, ['saleAreaName', 'saleAreaUuid', 'templateCityName', 'templateCityUuid']))
      const reduceList = skuList.reduce((value, item) => {
        const concatItem = {
          ...item, // 商品信息
          ...this.getInitPriceVo(), // 初始化价格
          ...this.taxRateInvoiceInfo, // 税类信息
          purchasePriceType: this.purchaseType, // 供货价格方式
          purchasePriceTypeStr: PURCHASE_TYPE_LABEL[this.purchaseType] ?? '', // 供货价格方式
        }
        this.referCities.finalResults.forEach(cityInfo => {
          value.push({ ...concatItem, ...getReferCityInfo(cityInfo) })
        })
        return value
      }, [])
      const priceMaps = await this.getSupplySkuCityPriceMaps(reduceList ?? [])
      const updateList = reduceList.map(item => ({
        ...item,
        ...priceMaps[`${item.skuNo}_${item.templateCityUuid}`] ?? {}
      }))
      return updateList ?? []
    },
    // 获取模板导出入参
    getExportParams (uuid) {
      const supplyAreaPriceParams = this.TableInfo.list.map(item => ({
        ...item,
        supplyUuid: this.supplierInfo.supplyUuid
      }))
      const data = {
        uuid,
        manySupply: '1', // 区分是否是多供
        productType: this.isMultiple ? '2' : '1', // 用来区分单计量还是多计量的，1是单计量，2是多计量
        skuNos: this.skuNos,
        supplyPriceType: this.purchaseType, // 供货价格方式 - 2为区域进价
        supplyAreaParams: this.referCities.list.map(item => ({ ...item,  })), // 参照关系列表
        supplyAreaPriceParams, // 多供进价表格数据
        ...this.supplierInfo, // 供应商信息
      }
      return data
    },
    // 获取提交入参
    getSubmitParams () {
      const supplyInfoParam = {
        supplyUuid: this.supplierInfo?.supplyUuid,
        saleAreaNo: this.saleAreaNos.join(','),
      }
      const data = {
        supplyInfoParam,
        isPurchaseMultiUnit: this.isPurchaseMultiUnit, // 单/多计量标识
        launchReason: EVENT_BUS._data.launchReason, // 发起原因
        skuInfoParams: this.skuNos.map(skuNo => ({ skuNo })),
        supplySkuAreaInfoParams: this.referCities.list,
        supplySkuPriceInfoParams: this.TableInfo.list
      }
      return data
    },
    // 提交进价信息
    async submitPurchaseInfo () {
      const data = this.getSubmitParams()
      const loadingFn = state => { this.btnLoading.submit = state }
      const res = await commitProductSupplySaleAreaSkuRecordForAlignmentSaleAreaService(data, loadingFn)
      if (res?.retStatus != '1') return
      // 无法提交处理
      if (res?.retData?.supplyPriceErrMap) {
        this.TableInfo.setColumns([ERROR_MSG_COL, ...this.TableInfo.columns])
        this.TableInfo.setList(res.retData)
        return this.$message.warning('存在禁止提交原因，无法提交单据')
      }
      // 正常提交处理
      this.$message.success('提交成功')
      this.$router.push({ name: 'chageFromManageList' })
    },
    // 设置售价预览信息
    async setPreviewSalePriceInfo () {
      const data = {
        supplyUuid: this.supplierInfo.supplyUuid,
        priceModels: this.TableInfo.list.map(item => _.pick(item, ['skuNo', 'templateCityUuid', 'mainUnitCostPrice'])),
        relationModels: this.referCities.list.map(item => _.pick(item, ['saleCityUuid', 'templateCityUuid', 'costPriceRatio']))
      }
      const loadingFn = state => { this.previewSalePrice.loading = state }
      const res = await prepareViewSalePriceService(data, loadingFn)
      if (res?.retData) {
        this.previewSalePrice.list = res.retData
        this.previewSalePrice.visible = true
      }
    },
    // 校验主计量成本价是否符合公式计算价格值
    validatePriceIsConsistent () {
      const getMainUnitCostPriceFn = this.isMultiple
        ? getPriceChangeForMultipleAdd
        : getPriceChangeForSingleAdd
      const hasInconsistent = this.TableInfo.list.some(
        item => item.mainUnitCostPrice != getMainUnitCostPriceFn(item)
      )
      return hasInconsistent
    },
    // 切换供货价格方式警告提示
    confirmBySwitchPurchaseType (val) {
      this.$confirm(
        '切换进价类型后会清空设置好的参照城市以及进价信息，你确定要切换吗',
        '提示',
        { type: 'warning' }
      ).then(() => {
        this.TableInfo.clearList() // 切换重置表格数据
        this.referCities.list = [] // 清空参照信息
      }).catch(() => {
        if (val == PURCHASE_TYPE.Unify) { this.purchaseType = PURCHASE_TYPE.Area }
        if (val == PURCHASE_TYPE.Area) { this.purchaseType = PURCHASE_TYPE.Unify }
      })
    },
  }
}
</script>
<style lang="less" scoped>
.refer-cities-wrap {
  display: flex;
  align-items: center;
}
.table-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
}
</style>
